<template>
    <div>
        <div>
            <el-button-group>
                <el-button type="warning" icon="el-icon-edit" @click="add"
                    >新增</el-button
                >
                <el-button
                    type="info"
                    icon="el-icon-close"
                    @click="deleteSelected"
                    >删除选中</el-button
                >
                <el-button
                    type="danger"
                    icon="el-icon-view"
                    @click="selectAllPositive"
                    >选择当前页全部阳性数据</el-button
                >
            </el-button-group>
            <el-button
                class="share_btn"
                type="success"
                icon="el-icon-share"
                @click="broadcast"
                >广播选中数据</el-button
            >
        </div>
        <div class="table_box">
            <el-table
                border
                ref="table"
                v-loading="isTableDataLoading"
                :data="tableData"
                @selection-change="handleSelectionChange"
                header-row-class-name="tableRow"
                :row-class-name="tableRowClassName"
            >
                <el-table-column
                    type="selection"
                    width="55"
                    max-height="800"
                    align="center"
                >
                </el-table-column>
                <el-table-column label="序号" width="70" align="center">
                    <template slot-scope="scope">{{
                        pageSize * (currentPage - 1) + scope.$index + 1
                    }}</template>
                </el-table-column>
                <el-table-column
                    prop="name"
                    label="姓名"
                    width="150"
                    align="center"
                >
                </el-table-column>
                <el-table-column label="状态" width="150" align="center"
                    ><template slot-scope="scope">{{
                        scope.row.positive == 0
                            ? "阴性"
                            : scope.row.positive == 1
                            ? "阳性"
                            : "密接"
                    }}</template>
                </el-table-column>
                <el-table-column label="日期" width="300" align="center">
                    <template slot-scope="scope">{{
                        formatDate(scope.row.date)
                    }}</template>
                </el-table-column>
                <el-table-column
                    prop="hash_code"
                    label="哈希码"
                    align="center"
                    show-overflow-tooltip
                    class-name="equalWidthFont"
                >
                </el-table-column>
            </el-table>
            <el-pagination
                class="pagination"
                @current-change="handleCurrentChange"
                @size-change="handleSizeChange"
                :current-page.sync="currentPage"
                :page-size="pageSize"
                :total="total"
                :page-sizes="[10, 15, 20, 25, 30]"
                layout="sizes, prev, pager, next, jumper"
            >
            </el-pagination>
        </div>
        <el-dialog
            :title="dialogTableBroadcastTitle"
            :visible.sync="dialogTableBroadcastVisible"
            width="75%"
        >
            <el-table
                :data="multipleSelection"
                header-row-class-name="tableRow"
                row-class-name="tableRow"
            >
                <el-table-column
                    type="index"
                    label="序号"
                    width="80"
                    align="center"
                ></el-table-column>
                <el-table-column
                    property="name"
                    label="姓名"
                    width="150"
                    align="center"
                ></el-table-column
                ><el-table-column label="日期" width="240" align="center"
                    ><template slot-scope="scope">{{
                        formatDate(scope.row.date)
                    }}</template></el-table-column
                >
                <el-table-column label="状态" width="150" align="center"
                    ><template slot-scope="scope">{{
                        scope.row.positive == 0
                            ? "阴性"
                            : scope.row.positive == 1
                            ? "阳性"
                            : "密接"
                    }}</template></el-table-column
                >
                <el-table-column
                    prop="hash_code"
                    label="哈希码"
                    align="center"
                    class-name="equalWidthFont"
                    show-overflow-tooltip
                ></el-table-column>
            </el-table>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialogTableBroadcastVisible = false"
                    >取 消</el-button
                >
                <el-button
                    type="warning"
                    @click="broadcastSubmit"
                    v-loading.fullscreen.lock="fullscreenLoading"
                    >确 定</el-button
                >
            </span>
        </el-dialog>
        <el-dialog
            title="新增信息"
            :visible.sync="dialogAddFormVisible"
            width="55%"
            @close="dialogAddFormClose"
        >
            <el-form ref="addForm" :model="addForm" :rules="addFormRules">
                <el-form-item
                    label="姓名"
                    prop="name"
                    :label-width="addFormLabelWidth"
                >
                    <el-input
                        v-model="addForm.name"
                        style="width: 60%"
                    ></el-input>
                </el-form-item>
                <el-form-item
                    label="哈希码"
                    prop="hash_code"
                    :label-width="addFormLabelWidth"
                >
                    <el-input v-model="addForm.hash_code">
                        <el-button
                            slot="append"
                            icon="el-icon-camera"
                            style="font-size: 16px"
                            @click="addFormStartCamera"
                        >
                        </el-button
                    ></el-input>
                </el-form-item>
                <el-form-item
                    label="状态"
                    prop="positive"
                    :label-width="addFormLabelWidth"
                >
                    <el-radio-group v-model="addForm.positive">
                        <el-radio :label="0" class="positive0">阴性</el-radio>
                        <el-radio :label="1" class="positive1">阳性</el-radio>
                        <!-- <el-radio :label="2" class="positive2">密接</el-radio> -->
                    </el-radio-group>
                    <!-- <el-select
                        v-model="addForm.positive"
                        placeholder="请选择状态"
                        style="width: 60%"
                    >
                        <el-option label="阴性" :value="0"></el-option>
                        <el-option label="阳性" :value="1"></el-option>
                        <el-option label="密接" :value="2"></el-option>
                    </el-select> -->
                </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="dialogAddFormVisible = false"
                    >取 消</el-button
                >
                <el-button type="warning" @click="addFormSubmit"
                    >确 定</el-button
                >
            </div>
        </el-dialog>
        <el-dialog
            title="扫描二维码"
            :visible.sync="dialogCameraVisible"
            width="70%"
            @close="dialogCameraClose"
        >
            <div
                id="loadingMessage"
                ref="loadingMessage"
                v-show="isLoadingMessageShow"
            >
                {{ loadingMessage }}
            </div>
            <video id="video" ref="video" v-show="isVideoShow"></video>
            <canvas
                id="canvasElement"
                ref="canvasElement"
                v-show="isCanvasElementShow"
            ></canvas>
            <div id="output" ref="output" v-show="isOutputShow">
                <div
                    id="outputMessage"
                    ref="outputMessage"
                    v-show="isOutputMessageShow"
                >
                    没有发现二维码👻请将二维码对准摄像头
                </div>
                <div v-show="isOutputDataShow">
                    <b>Data:</b>
                    <span id="outputData">{{ outputData }}</span>
                </div>
                <el-select
                    class="cameraSelect"
                    size="mini"
                    v-model="cameraSelectNow"
                    placeholder="请选择要使用的摄像头"
                >
                    <el-option
                        v-for="item in camerasOptions"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value"
                    >
                    </el-option>
                </el-select>
            </div>
        </el-dialog>
    </div>
</template>

<script>
import axios from "axios";
import jsQR from "jsqr";
export default {
    data() {
        return {
            hospitslName: "",
            currentPage: 1,
            tableData: [],
            isTableDataLoading: false,
            multipleSelection: [],
            total: 0,
            pageSize: 0,
            dialogTableBroadcastTitle: "进行广播",
            dialogTableBroadcastVisible: false,
            fullscreenLoading: false,
            dialogAddFormVisible: false,
            addFormLabelWidth: "90px",
            dialogCameraVisible: false,
            cameraSelectNow: "",
            camerasOptions: [],
            mediaSreamTrack: undefined,
            canvas: undefined,
            isLoadingMessageShow: true,
            loadingMessage: "🎥 访问用户录像设备中... 🎥",
            isVideoShow: false,
            isCanvasElementShow: false,
            isOutputShow: false,
            isOutputMessageShow: true,
            isOutputDataShow: false,
            outputData: "",
            requestAF: undefined,
            addForm: {
                name: "",
                positive: "",
                hash_code: "",
            },
            addFormRules: {
                name: [
                    {
                        required: true,
                        message: "请输入姓名",
                        trigger: "blur",
                    },
                ],
                hash_code: [
                    {
                        required: true,
                        message: "请输入哈希码",
                        trigger: "blur",
                    },
                ],
                positive: [
                    {
                        required: true,
                        message: "请选择状态",
                        trigger: "change",
                    },
                ],
            },
        };
    },
    mounted() {
        this.getData();
    },
    methods: {
        getData(page, pageSize) {
            this.isTableDataLoading = true;
            axios
                .post("/api/hdet/query", {
                    page: page || 1,
                    pageSize: pageSize || 10,
                })
                .then((res) => {
                    this.tableData = res.data.res;
                    this.pageSize = res.data.pageSize;
                    this.total = res.data.total;
                    this.isTableDataLoading = false;
                });
        },
        // 将毫秒时间戳转换成年月日时分秒
        formatDate(timeStamp) {
            var date = new Date(Number(timeStamp));
            var y = 1900 + date.getYear();
            var m = "0" + (date.getMonth() + 1);
            var d = "0" + date.getDate();
            var h = "0" + date.getHours();
            var minute = "0" + date.getMinutes();
            var second = "0" + date.getSeconds();
            return (
                y +
                "-" +
                m.substring(m.length - 2, m.length) +
                "-" +
                d.substring(d.length - 2, d.length) +
                " " +
                h.substring(h.length - 2, h.length) +
                ":" +
                minute.substring(minute.length - 2, minute.length) +
                ":" +
                second.substring(second.length - 2, second.length)
            );
        },
        handleSelectionChange(val) {
            this.multipleSelection = val;
        },
        selectAllPositive() {
            for (let i = 0; i < this.multipleSelection.length; i++) {
                if (this.multipleSelection[i].positive == 0) {
                    this.$refs["table"].clearSelection();
                    break;
                }
            }
            this.tableData.forEach((item) => {
                if (item.positive == 1) {
                    this.$refs["table"].toggleRowSelection(item);
                }
            });
        },
        tableRowClassName({ row, rowIndex }) {
            if (row.positive == 1) {
                return "tableRow warning-row";
            } else if (row.positive == 2) {
                return "tableRow close-contact";
            }
            return "tableRow green";
        },
        handleCurrentChange(page) {
            this.getData(page, this.pageSize);
        },
        handleSizeChange(size) {
            this.getData(this.currentPage, size);
        },
        broadcast() {
            if (this.multipleSelection.length == 0) return;
            this.dialogTableBroadcastVisible = true;
            for (let i = 0; i < this.multipleSelection.length; i++) {
                if (this.multipleSelection[i].positive == 0) {
                    this.dialogTableBroadcastTitle =
                        "进行广播" + "（注意：当前选中包含阴性数据）";
                    break;
                } else {
                    this.dialogTableBroadcastTitle = "进行广播";
                }
            }
        },
        broadcastSubmit() {
            this.fullscreenLoading = true;
            axios
                .post("/api/hdet/broadcast", {
                    type: "broadcast",
                    time_id: new Date().getTime(),
                    content: this.multipleSelection.map((item) => {
                        return { hash_code: item.hash_code, depth: 0 };
                    }),
                })
                .then((res) => {
                    setTimeout(() => {
                        this.fullscreenLoading = false;
                        this.dialogTableBroadcastVisible = false;
                        this.$refs.table.clearSelection();
                    }, 600);
                    if (res.data.h_code != -1 && res.data.msg.success == true) {
                        this.$notify({
                            title: "成功",
                            message: "广播已完成...",
                            duration: 800,
                            type: "success",
                        });
                        axios
                            .post(
                                "/api/hdet/add_broadcast_record",
                                this.multipleSelection
                            )
                            .then((res) => {
                                if (res.data.h_code == -1) {
                                    this.$notify({
                                        title: "失败",
                                        message: res.data.msg,
                                        type: "error",
                                    });
                                }
                            });
                    } else {
                        this.$notify({
                            title: "失败",
                            message: res.data.msg,
                            type: "error",
                        });
                    }
                });
        },
        deleteSelected() {
            if (this.multipleSelection.length == 0) return;
            let obj = this.multipleSelection.map((item) => {
                return item.id;
            });
            this.$confirm("确认进行删除选中的信息吗？", {
                type: "warning",
                confirmButtonClass: "el-button--warning",
            })
                .then(() => {
                    axios.post("/api/hdet/delete", { ids: obj }).then((res) => {
                        if (res.data.h_code == -1) {
                            this.$notify({
                                title: "删除失败",
                                message: res.data.msg,
                                type: "error",
                            });
                        } else {
                            this.$notify({
                                title: "成功",
                                duration: 800,
                                message: "删除成功",
                                type: "success",
                            });
                            this.getData();
                        }
                    });
                })
                .catch(() => {});
        },
        add() {
            this.dialogAddFormVisible = true;
            if (navigator.mediaDevices.getUserMedia) {
                navigator.mediaDevices
                    .enumerateDevices()
                    .then((deviceInfos) => {
                        this.camerasOptions = [];
                        // this.cameraSelectNow = "";
                        for (let i = 0; i !== deviceInfos.length; i++) {
                            let deviceInfo = deviceInfos[i];
                            let option = {};
                            if (deviceInfo.kind === "videoinput") {
                                option.value = deviceInfo.deviceId;
                                option.label =
                                    deviceInfo.label || "camera " + i;
                                this.camerasOptions.push(option);
                            }
                        }
                    });
            } else {
                this.$notify.error({
                    title: "错误",
                    message: "你的电脑或此浏览器暂无法使用摄像头",
                });
            }
        },
        dialogAddFormClose() {
            this.addForm = {
                name: "",
                positive: "",
                hash_code: "",
            };
        },
        addFormSubmit() {
            this.$refs["addForm"].validate((valid) => {
                if (valid) {
                    axios.post("/api/hdet/add", this.addForm).then((res) => {
                        if (res.data.h_code != -1) {
                            this.$notify({
                                title: "成功",
                                duration: 800,
                                message:
                                    "已成功添加" +
                                    this.addForm.name +
                                    "的数据。",
                                type: "success",
                            });
                            this.getData();
                            this.dialogAddFormVisible = false;
                            this.addForm = {
                                name: "",
                                positive: "",
                                hash_code: "",
                            };
                        } else {
                            this.$notify({
                                title: "添加失败",
                                message: res.data.msg,
                                type: "error",
                            });
                        }
                    });
                } else {
                    return false;
                }
            });
        },
        addFormStartCamera() {
            this.dialogCameraVisible = true;
            this.$nextTick(() => {
                this.canvas = this.$refs["canvasElement"].getContext("2d");
            });
            let constrains = {
                video: {
                    deviceId:
                        this.cameraSelectNow == ""
                            ? this.camerasOptions[0].value
                            : this.cameraSelectNow,
                    facingMode: "environment",
                },
            };
            // 暂未适配多浏览器，现Chrome测试ok
            navigator.mediaDevices.getUserMedia(constrains).then((stream) => {
                this.mediaSreamTrack = stream.getTracks()[0];
                this.$refs["video"].srcObject = stream;
                this.$refs["video"].setAttribute("playsinline", true);
                this.$refs["video"].play();
                requestAnimationFrame(this.tick);
            });
        },
        dialogCameraClose() {
            this.mediaSreamTrack.stop();
            this.$refs["video"].srcObject = null;
            this.$refs["video"].pause();
            this.dialogCameraVisible = false;
        },
        tick() {
            this.loadingMessage = "⌛ Loading ...";
            if (this.$refs["video"].readyState === video.HAVE_ENOUGH_DATA) {
                this.isLoadingMessageShow = false;
                this.isCanvasElementShow = true;
                this.isOutputShow = true;
                this.$refs["canvasElement"].height =
                    this.$refs["video"].videoHeight;
                this.$refs["canvasElement"].width =
                    this.$refs["video"].videoWidth;
                this.canvas.drawImage(
                    this.$refs["video"],
                    0,
                    0,
                    this.$refs["canvasElement"].width,
                    this.$refs["canvasElement"].height
                );
                let imageData = this.canvas.getImageData(
                    0,
                    0,
                    this.$refs["canvasElement"].width,
                    this.$refs["canvasElement"].height
                );
                let code = jsQR(
                    imageData.data,
                    imageData.width,
                    imageData.height,
                    {
                        inversionAttempts: "dontInvert",
                    }
                );
                if (code) {
                    this.isOutputMessageShow = false;
                    this.isOutputDataShow = true;
                    this.outputData = code.data;
                    this.mediaSreamTrack.stop();
                    this.dialogCameraVisible = false;
                    let res = JSON.parse(code.data);
                    this.addForm.name = res.name;
                    this.addForm.hash_code = res.hash_code;
                    this.outputData = "";
                } else {
                    this.isOutputMessageShow = true;
                    this.isOutputDataShow = false;
                }
            }
            this.requestAF = requestAnimationFrame(this.tick);
        },
    },
    watch: {
        cameraSelectNow(val) {
            this.dialogCameraClose();
            this.addFormStartCamera();
        },
    },
};
</script>

<style>
.share_btn {
    float: right;
}
.table_box {
    margin-top: 20px;
}
.el-table .tableRow {
    height: 55px;
}
.el-table .warning-row {
    background: oldlace;
}
/* .el-table .close-contact {
    background: #ffecb7;
}
.el-table .green {
    background: #ddfaae;
} */
.positive0 .el-radio__input.is-checked .el-radio__inner {
    border-color: #43dc7d;
    background: #43dc7d;
}
.positive0 .el-radio__input.is-checked + .el-radio__label {
    color: #43dc7d;
}
.positive1 .el-radio__input.is-checked .el-radio__inner {
    border-color: #e6453c;
    background: #e6453c;
}
.positive1 .el-radio__input.is-checked + .el-radio__label {
    color: #e6453c;
}
.positive2 .el-radio__input.is-checked .el-radio__inner {
    border-color: #e6a23c;
    background: #e6a23c;
}
.positive2 .el-radio__input.is-checked + .el-radio__label {
    color: #e6a23c;
}
.pagination {
    text-align: center;
    margin-top: 20px;
    margin-left: -30px;
}
#loadingMessage {
    text-align: center;
    padding: 40px;
    background-color: #eee;
}
#canvasElement {
    width: 100%;
}
#output {
    margin-top: 20px;
    background: #eee;
    padding: 10px;
    padding-bottom: 0;
}
#output div {
    padding-bottom: 10px;
    word-wrap: break-word;
}
.cameraSelect {
    position: absolute;
    right: 30px;
    bottom: 15px;
}
</style>